Skip to main content

Vue3 Attributes Binding

In Vue3, when using a child component in the parent component, the properties passed in will be bound to the root element of the child component by default. For example:

<Button
  size="small"
  @click="onClick"
  @focus="onFocus"
  @mouseover="onMouseover"> Test </Button>

Child component is as follows:

<template>
  <div>
    <button>Click me</button>
  </div>
</template>

Then, the three events on the Button component will be bound to the div by default, not the button.

Q: If the child component is simple, you can directly enjoy the convenience provided by Vue. If the child component is complex, how to manually prevent default binding?

A: In the script tag of the child component, you need to disable inheritAttrs, use $attrs to get all attributes, and use v-bind="$attrs" on the element where you want to bind the attributes:

<template>
  <div>
    <button v-bind="$attrs">
    Click me
    </button>
  </div>
</template>

<script>
export default {
	inheritAttrs: false,
};
</script>
// ...

Q: If there are many attributes and you want to bind them to more elements, how can you achieve this?

A: You can destructure the context in setup and bind it to the corresponding elements separately.

<template>
  <div :size="size">
    <button @Click="onClick">
    Click me
    </button>
  </div>
</template>

<script>
export default {
	inheritAttrs: false,
	setup(props, context) {
		const {onClick, onMouseover, onFocus} = context.attrs
		return {size, onClick, onMouseover, onFocus}
	}
};
</script>
// ...

Too troublesome?

You can also use the ES6 rest operator to bind in batches.

<template>
  <div :size="size">
    <button v-bind="actions">
    Click me
    </button>
  </div>
</template>

<script>
export default {
	inheritAttrs: false,
	setup(props, context) {
		const {size, ...actions} = context.attrs
		return {size, actions}
	}
};
</script>
// ...